package com.lp.guoguo.controller;

import com.lp.guoguo.common.Result;
import com.lp.guoguo.common.ResultCode;
import com.lp.guoguo.constant.SecurityConstants;
import com.lp.guoguo.domain.Users;
import com.lp.guoguo.dto.*;
import com.lp.guoguo.security.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;
import com.lp.guoguo.service.UsersService;
import com.lp.guoguo.util.JwtUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.context.SecurityContextHolder;
import java.util.Date;

@RestController
@RequestMapping("/api/auth")
@RequiredArgsConstructor
public class AuthController {
    private final UsersService usersService;
    private final JwtUtil jwtUtil;
    private final PasswordEncoder passwordEncoder;

    @PostMapping("/login")
    public Result<?> loginByPassword(@RequestBody LoginRequest request) {
        Users user = usersService.lambdaQuery()
            .eq(Users::getUsername, request.getUsername())
            .one();
            
        if (user == null || !passwordEncoder.matches(request.getPassword(), user.getPassword())) {
            return Result.failed(ResultCode.USER_LOGIN_FAILED);
        }

        updateLoginInfo(user);
        String token = jwtUtil.generateToken(new UserDetails(user));
        return Result.success(user, token);
    }

    @PostMapping("/login/code")
    public Result<?> loginByCode(@RequestBody CodeLoginRequest request) {
        // TODO: Implement verification code validation
        Users user = usersService.lambdaQuery()
            .eq(Users::getEmail, request.getEmail())
            .one();
            
        if (user == null) {
            return Result.failed(ResultCode.USER_NOT_EXIST);
        }

        updateLoginInfo(user);
        String token = jwtUtil.generateToken(new UserDetails(user));
        return Result.success(user, token);
    }

    @PostMapping("/register")
    public Result<?> register(@RequestBody RegisterRequest request) {
        // Check if username exists
        if (usersService.lambdaQuery().eq(Users::getUsername, request.getUsername()).exists()) {
            return Result.failed(ResultCode.USER_ACCOUNT_ALREADY_EXIST);
        }

        Users user = new Users();
        user.setUsername(request.getUsername());
        user.setPassword(passwordEncoder.encode(request.getPassword()));
        user.setEmail(request.getEmail());
        user.setNickname(request.getNickname());
        user.setStatus(1);
        user.setCreatedAt(new Date());
        user.setUpdatedAt(new Date());

        usersService.save(user);

        return Result.success();
    }

    @PostMapping("/logout")
    public Result<?> logout() {
        SecurityContextHolder.clearContext();
        return Result.success();
    }

    @PostMapping("/token/refresh")
    public Result<?> refreshToken(@RequestHeader("Authorization") String token) {
        if (token != null && token.startsWith(SecurityConstants.JWT.TOKEN_PREFIX)) {
            token = token.substring(SecurityConstants.JWT.TOKEN_PREFIX.length());
            String refreshedToken = jwtUtil.refreshToken(token);
            return Result.success(null, refreshedToken);
        }
        return Result.failed(ResultCode.TOKEN_INVALID);
    }

    @PutMapping("/password")
    public Result<?> updatePassword(@RequestBody UpdatePasswordRequest request) {
        String username = SecurityContextHolder.getContext().getAuthentication().getName();
        Users user = usersService.lambdaQuery()
            .eq(Users::getUsername, username)
            .one();

        if (!passwordEncoder.matches(request.getOldPassword(), user.getPassword())) {
            return Result.failed(ResultCode.OLD_PASSWORD_ERROR);
        }

        user.setPassword(passwordEncoder.encode(request.getNewPassword()));
        user.setUpdatedAt(new Date());
        usersService.updateById(user);
        return Result.success();
    }

    @PutMapping("/profile")
    public Result<?> updateProfile(@RequestBody UpdateProfileRequest request) {
        String username = SecurityContextHolder.getContext().getAuthentication().getName();
        Users user = usersService.lambdaQuery()
            .eq(Users::getUsername, username)
            .one();

        user.setNickname(request.getNickname());
        user.setAvatarUrl(request.getAvatarUrl());
        user.setEmail(request.getEmail());
        user.setUpdatedAt(new Date());
        usersService.updateById(user);
        return Result.success();
    }

    @GetMapping("/profile")
    public Result<?> getProfile() {
        String username = SecurityContextHolder.getContext().getAuthentication().getName();
        Users user = usersService.lambdaQuery()
            .eq(Users::getUsername, username)
            .one();
        return Result.success(user);
    }

    private void updateLoginInfo(Users user) {
        user.setLastLoginTime(new Date());
//        user.setLastLoginIp(ServletUtil.getClientIP()); // You'll need to add hutool-all dependency
        user.setUpdatedAt(new Date());
        usersService.updateById(user);
    }

}